package com.df.library.net.handler;


import com.df.library.net.condition.IProtocolPredicate;
import com.df.library.uitls.ClassUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class ProtocolSelectHandler extends ChannelInboundHandlerAdapter {

    private List<Class<? extends IProtocolPredicate>> conditions = new LinkedList<>();
    private static Map<Class<? extends IProtocolPredicate>,IProtocolPredicate> sharedPredicates = new HashMap<>();


    public void addCondition(Class<? extends IProtocolPredicate> condition){
        if(conditions.contains(condition)){
            log.error("ProtocolSelectHandler 中重复添加协议判断，类名："+condition.getClass().getName());
            return;
        }
        conditions.add(condition);
        if(ClassUtils.isShareable(condition)){
            try {
                sharedPredicates.put(condition,condition.newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public void addConditions(List<Class<? extends IProtocolPredicate>> conditions){
        for (Class<? extends IProtocolPredicate> condition : conditions) {
            addCondition(condition);
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        if(conditions.size()==0){
            super.channelRead(ctx, msg);
            return;
        }
        for (Class<? extends IProtocolPredicate> condition : conditions) {

            IProtocolPredicate predicate = sharedPredicates.get(condition);
            if(predicate==null){
                predicate = condition.newInstance();
            }

            if(predicate.check(ctx,byteBuf)){
                predicate.channelInit(ctx);
//                super.channelRead(ctx, msg);
                //新加了处理器，从头开始传消息
                ctx.pipeline().fireChannelRead(msg);
                return;
            }
        }
        //有未知的协议
        ctx.pipeline().writeAndFlush(Unpooled.wrappedBuffer("未知协议".getBytes())).addListener(ChannelFutureListener.CLOSE);
    }



}
